﻿using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;

namespace FXCopAddIn.Classes
{
    public sealed class BaseAnalysis
    {
        #region Fields

        private Microsoft.VisualStudio.Shell.ErrorListProvider _errorlistprovider;
        private EventHandler _taskErrorNavigate = null;
        private Projects _projetosSolucao = null;
        private string _prefixError;

        #endregion

        #region Construtor

        public BaseAnalysis(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceprovider, EventHandler onTaskErrorNavigate, Projects projetosSolucao, string prefixError)
        {
            IServiceProvider IProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(serviceprovider);
            _errorlistprovider = new Microsoft.VisualStudio.Shell.ErrorListProvider(IProvider);
            _taskErrorNavigate = onTaskErrorNavigate;
            _projetosSolucao = projetosSolucao;
            _prefixError = prefixError;
        }

        #endregion

        #region Public Methods

        public BaseAddIn.Enums.Resultado Analise(string projectName, BaseAddIn.Enums.StatusAddIn status, BaseAddIn.Analysis.Base analisador, out Exception exThread)
        {
            Exception exAux = null;
            BaseAddIn.Enums.Resultado resultado = BaseAddIn.Enums.Resultado.Sucesso;

            System.Threading.Thread t = new System.Threading.Thread(delegate()
                                                                    {
                                                                        try
                                                                        {
                                                                            Project projetoAnalisar = null;

                                                                            foreach (Project projetoSolucao in _projetosSolucao)
                                                                            {
                                                                                if (projetoSolucao.Name == projectName)
                                                                                {
                                                                                    projetoAnalisar = projetoSolucao;
                                                                                    break;
                                                                                }
                                                                            }

                                                                            analisador.PreparaAnalise();

                                                                            if (projetoAnalisar != null)
                                                                            {
                                                                                analisador.Analise(projetoAnalisar);
                                                                            }

                                                                            GeraErros(analisador.ListaProblemas, status);
                                                                        }
                                                                        catch(Exception ex)
                                                                        {
                                                                            exAux = ex;
                                                                        }
                                                                    });

            t.Name = String.Concat("FXCopAddIn_", DateTime.Now.ToString("yyyyMMddhhmmss"));
            t.Start();

            while (t.ThreadState != System.Threading.ThreadState.Stopped
                   && t.ThreadState != System.Threading.ThreadState.Aborted)
            {
                System.Windows.Forms.Application.DoEvents();
            }

            if (exAux != null)
                exThread = exAux;
            else
                exThread = null;

            analisador.Dispose();

            if (_errorlistprovider.Tasks.Count > 0
                && status == BaseAddIn.Enums.StatusAddIn.LigadoErros)
            {
                resultado = BaseAddIn.Enums.Resultado.Erro;
            }

            return resultado;
        }

        public int MostraErros()
        {
            if (_errorlistprovider.Tasks.Count > 0)
                _errorlistprovider.Show();

            return _errorlistprovider.Tasks.Count;
        }

        public void Dispose()
        {
            if (_errorlistprovider != null)
            {
                for (int i = 0; i < _errorlistprovider.Tasks.Count; i++)
                {
                    _errorlistprovider.Tasks[i].Navigate -= _taskErrorNavigate;
                }

                _errorlistprovider.Tasks.Clear();
                _errorlistprovider = null;
            }

            _taskErrorNavigate = null;
            _projetosSolucao = null;

            GC.Collect();
        }

        public void GeraErros(List<BaseAddIn.Rules.ProblemAddIn> listaProblemas, BaseAddIn.Enums.StatusAddIn status)
        {
            BaseAddIn.Rules.ProblemAddIn problema;

            for (int i = 0; i < listaProblemas.Count; i++)
            {
                problema = listaProblemas[i];

                Microsoft.VisualStudio.Shell.ErrorTask task = new Microsoft.VisualStudio.Shell.ErrorTask();
                task.Category = Microsoft.VisualStudio.Shell.TaskCategory.BuildCompile;

                task.Text = String.Concat(_prefixError,
                                          "\r\n",
                                          problema.Erro);

                task.Priority = problema.Priority;

                task.ErrorCategory = (status == BaseAddIn.Enums.StatusAddIn.LigadoWarnings)
                                                    ? Microsoft.VisualStudio.Shell.TaskErrorCategory.Warning
                                                    : Microsoft.VisualStudio.Shell.TaskErrorCategory.Error;

                task.Document = problema.Document;
                task.Line = problema.Line;
                task.Column = problema.Column;

                task.Navigate += new EventHandler(_taskErrorNavigate);
                _errorlistprovider.Tasks.Add(task);
            }

            //Criar erro método 2
            /*=====================================================================================*/

            //OutputWindow outputWindow;
            //OutputWindowPane pane;
            //Window window;

            //window = (Window)_applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
            //outputWindow = (OutputWindow)window.Object;
            //pane = outputWindow.OutputWindowPanes.Item(Microsoft.VisualStudio.VSConstants.GUID_BuildOutputWindowPane.ToString("B"));
            //pane.OutputTaskItemString("message", vsTaskPriority.vsTaskPriorityHigh, "MyCategory", vsTaskIcon.vsTaskIconCompile, "Form1.cs", 0, "message", true);

            //_applicationObject.ExecuteCommand("Build.Cancel", "");

            //pane.OutputString(Environment.NewLine + "Error during add-in processing - Build Stopped" + Environment.NewLine + Environment.NewLine);

            //((EnvDTE80.DTE2)_applicationObject).ToolWindows.ErrorList.Parent.Activate();

            /*=====================================================================================*/
        }

        #endregion
    }
}
